﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ServiceModel.DomainServices.Client;
using System.ServiceModel.DomainServices.Server;
using System.Windows;
using System.Windows.Data;
using Agility.Web.Models.DomainModel;
using Agility.Web.Services;
using FirstLook.ServiceModel.DomainServices.Client.Security;
using NLog;
using System.Collections.Specialized;

namespace Agility.ViewModels
{
    public class MyIdeasViewModel : INotifyPropertyChanged
    {
        Visibility myIdeasVisibility;
        AuthorizationSource registerdeUserSource;
        LoadOperation<Epic> loadOp;
        List<Epic> myIdeas;

        public event PropertyChangedEventHandler PropertyChanged;

        Logger logger = LogManager.GetCurrentClassLogger();

        public MyIdeasViewModel()
        {
            this.logger.Debug("--> Entering constructor");
            this.DomainContext = new RequirementsManagementContext();
            this.logger.Debug("Created DomainContext");
            this.Initialize();
            this.logger.Debug("<-- Leaving constructor");
        }

        public MyIdeasViewModel(DomainClient domainClient)
        {
            this.DomainContext = new RequirementsManagementContext(domainClient);
            this.Initialize();
        }

        private void Initialize()
        {
            this.logger.Debug("--> Entering Initialize");
            this.myIdeas = new List<Epic>();
            this.MyEpics = new PagedCollectionView(myIdeas);
            this.logger.Debug("Initialized MyEpics");
            this.MyEpics.SortDescriptions.Add(new SortDescription("CreationDate", ListSortDirection.Ascending));
            this.MyEpics.SortDescriptions.Add(new SortDescription("Title", ListSortDirection.Ascending));
            this.MyEpics.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(MyEpics_CollectionChanged);
            this.registerdeUserSource = new AuthorizationSource(new[] { new RequiresRoleAttribute("Registered User") });
            this.registerdeUserSource.PropertyChanged += new PropertyChangedEventHandler(registerdeUserSource_PropertyChanged);
            this.CalculateAuthorization();
            this.logger.Debug("<-- Leaving constructor");
        }

        void MyEpics_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    foreach (Epic epic in e.NewItems)
                    {
                        if (epic.EntityState == EntityState.Detached)            
                            this.DomainContext.Epics.Add(epic);
                    }
                    break;
                case NotifyCollectionChangedAction.Remove:
                    break;
                case NotifyCollectionChangedAction.Replace:
                    break;
                case NotifyCollectionChangedAction.Reset:
                    break;
                default:
                    break;
            }
        }

        public void Cleanup()
        {
            this.registerdeUserSource.PropertyChanged -= new PropertyChangedEventHandler(registerdeUserSource_PropertyChanged);
        }

        void registerdeUserSource_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            CalculateAuthorization();
        }

        private void RaisePropertyChanged(string propertyName)
        {
            logger.Debug("--> Entering RaisePropertyChanged");
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                this.logger.Debug("Raised PropertyChangedEvent for {0}", propertyName);
            }
            logger.Debug("<-- Leaving RaisePropertyChanged");
        }

        public PagedCollectionView MyEpics { get; private set; }

        public RequirementsManagementContext DomainContext { get; private set; }

        public Visibility MyIdeasVisibility 
        {
            get 
            {
                this.logger.Debug("--> Entering MyIdeasVisibility getter");
                this.logger.Trace<Visibility>("Visibility is {0}", this.myIdeasVisibility);
                this.logger.Debug("<-- Leaving MyIdeasVisibility getter");
                return this.myIdeasVisibility;
            }
            private set
            {
                if (this.myIdeasVisibility != value)
                {
                    this.logger.Debug("--> Entering MyIdeasVisibility setter");
                    this.myIdeasVisibility = value;
                    this.logger.Trace<Visibility>("Set MyIdeasVisibility to {0}", this.myIdeasVisibility);
                    this.RaisePropertyChanged("MyIdeasVisibility");
                    this.logger.Debug("<-- Leaving MyIdeasVisiblity setter");
                }
            }
        }

        void GetMyIdeas()
        {
            this.logger.Debug("--> Entering GetMyIdeas");
            EntityQuery<Epic> query = this.DomainContext.GetMyIdeasQuery();
            this.loadOp = this.DomainContext.Load(query);
            this.loadOp.Completed += new EventHandler(loadOp_Completed);
            logger.Debug("Started retrieval of MyIdeas");
            this.logger.Debug("--> Leaving GetMyIdeas");
        }

        void loadOp_Completed(object sender, EventArgs e)
        {
            this.logger.Debug("Retrieving result of GetMyIdeas");
            this.loadOp.Completed -= new EventHandler(loadOp_Completed);
            this.myIdeas.Clear();
            this.myIdeas.AddRange(loadOp.Entities);
            this.MyEpics.CollectionChanged -= new NotifyCollectionChangedEventHandler(MyEpics_CollectionChanged);
            this.MyEpics.Refresh();
            this.MyEpics.MoveCurrentToFirst();
            this.MyEpics.CollectionChanged += new NotifyCollectionChangedEventHandler(MyEpics_CollectionChanged);
            this.logger.Debug("Updated MyEpics property");
            this.logger.Debug("Completed GetMyIdeas");
        }

        private void CalculateAuthorization()
        {
            logger.Debug("--> Entering CalculateAuthorization");
            if (this.registerdeUserSource.Result == AuthorizationResult.Allowed)
            {
                this.MyIdeasVisibility = Visibility.Visible;
                this.GetMyIdeas();
                this.logger.Debug("Fetching Epics");
            }
            else
                this.MyIdeasVisibility = Visibility.Collapsed;
            logger.Debug("<-- Leaving CalculateAuthorization");
        }

        public void SubmitChanges()
        {
            if (this.DomainContext.HasChanges && !this.DomainContext.IsSubmitting)
                this.DomainContext.SubmitChanges();
        }
    }
}
